home *** CD-ROM | disk | FTP | other *** search
Modula Implementation | 1994-09-22 | 7.7 KB | 218 lines |
- IMPLEMENTATION MODULE MACHINE;
-
- (*****************************************************************************)
- (* Um die Interruptmaske der CPU manipulieren zu koennen, wurde ein 'unsau- *)
- (* berer' Weg beschritten: Da bekannt ist, welche Register beim Aufruf einer *)
- (* XBIOS-Funktion gerettet werden, und auch ueber eine Systemvariable bekannt*)
- (* ist, an welcher Stelle sie gespeichert sind, kann das beim Uebergang in *)
- (* den Supervisormodus gerettete Statusregister manipuliert werden. *)
- (* Bei der Rueckkehr aus der Ausnahmebehandlung wird dann dieses veraenderte *)
- (* Statusregister in das SR der CPU geschrieben. *)
- (* Diese Vorgehensweise haengt natuerlich davon ab, dass die Anzahl der ge- *)
- (* retteten Register sich nicht veraendert; sollte dies bei einer spaeteren *)
- (* TOS-Version der Fall sein, muss der Offset fuer das Statusregister ent- *)
- (* sprechend geaendert werden. *)
- (* *)
- (* Eine andere Moeglichkeit waere es, je nach momentanem CPU-Modus direkt *)
- (* das Statusregister zu manipulieren, oder erst in den Supervisormodus zu *)
- (* schalten, das SR zu manipulieren, und danach wieder in den User-Modus zu *)
- (* gehen. Der momentane CPU-Modus muesste auf jeden Fall vorher abgefragt *)
- (* werden, denn waere die CPU im Supervisormodus beim Aufruf einer der beiden*)
- (* Funktionen, so wuerde das unbedingte "SuperOff" am Ende der Prozedur den *)
- (* User-Modus einschalten. Neben dem unerwuenschten Nebeneffekt, gaebe das *)
- (* evtl. Stacksalat, da der Moduswechsel auf unterschiedlichen Prozedurebenen*)
- (* geschaehe ( ob's tatsaechlich Aerger mit dem Stack gibt, habe ich aller- *)
- (* dings nicht ausprobiert ). *)
- (*___________________________________________________________________________*)
- (* 09-Feb-90 , hk Beginn *)
- (* 11-Feb-90 , hk erste Version *)
- (* 12-Feb-90 , hk "BREAKPOINT" neu *)
- (* 05-Mae-90 , hk *)
- (* Traps aus "TRAPdefs" importiert, *)
- (* die Adressparameter in "Read/WriteSysMem" als LONGCARD, damit auch *)
- (* sedezimale Konstanten moeglich sind. *)
- (*****************************************************************************)
-
- FROM SYSTEM IMPORT (* TYPE *) BYTE, ADDRESS,
- (* PROC *) VAL, REG, ADR, INLINE;
-
- FROM TRAPdefs IMPORT (* CONST*) d0,
- (* PROC *) XBIOS1l, GEMDOS1l;
-
- FROM MEMORY IMPORT (* PROC *) CopySmallMem;
-
-
- (*===========================================================================*)
- (*==== L O K A L ========================================================*)
-
- CONST Supexec = 38;
- Super = 32;
-
- VAR quelle,
- ziel : ADDRESS;
- laenge : CARDINAL;
-
- stack : LONGCARD;
-
- (*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*)
-
- PROCEDURE Copy;
- (*T*)
- BEGIN
- (* Da "Copy" parameterlos ist, kann sie mit XBIOS.Supexec
- * im Supervisormodus ausgefuehrt werden.
- *)
- CopySmallMem( quelle, ziel, laenge );
- END Copy;
-
-
- (*===========================================================================*)
-
-
- PROCEDURE ReadSysMem ((* EIN/ -- *) adr : LONGCARD;
- (* -- /AUS *) VAR wert : ARRAY OF BYTE );
- (*T*)
- BEGIN
- (* Die Parameter fuer die Kopierfunktion muessen
- * globalen Variablen zugewiesen werden, damit die
- * parameterlose Prozedur "Copy", die sie an die
- * eigentliche Kopierfunktion uebergibt, im Supervisor-
- * modus mit 'Supexec' ausgefuehrt werden kann.
- *)
-
- quelle := adr;
- ziel := ADR( wert );
- laenge := HIGH( wert ) + 1;
-
- XBIOS1l( ADR( Copy ), Supexec );
- END ReadSysMem;
-
- (*---------------------------------------------------------------------------*)
-
- PROCEDURE WriteSysMem ((* EIN/ -- *) adr : LONGCARD;
- (* EIN/ -- *) wert : ARRAY OF BYTE );
- (*T*)
- BEGIN
- quelle := ADR( wert );
- ziel := adr;
- laenge := HIGH( wert ) + 1;
-
- XBIOS1l( ADR( Copy ), Supexec );
- END WriteSysMem;
-
- (*---------------------------------------------------------------------------*)
-
- PROCEDURE CurrentCPUMode ( ): CPUMode;
- (*T*)
- BEGIN
- GEMDOS1l( 1D, Super );
- RETURN( VAL( CPUMode, -REG( d0 )));
- END CurrentCPUMode;
-
- (*---------------------------------------------------------------------------*)
-
- PROCEDURE SuperOn;
- (**)
- BEGIN
- IF CurrentCPUMode() = USER THEN
- GEMDOS1l( 0D, Super );
- stack := REG( d0 );
- (* Der alte Wert des Supervisor-Stackpointers
- * wird gemerkt, damit er beim Wechsel in den
- * User-Modus wieder auf seinen alten Wert
- * gesetzt werden kann.
- *)
- END;
- END SuperOn;
-
- (*---------------------------------------------------------------------------*)
-
- PROCEDURE SuperOff;
- (**)
- BEGIN
- IF CurrentCPUMode() = SUPERVISOR THEN
- GEMDOS1l( stack, Super );
- END;
- END SuperOff;
-
- (*---------------------------------------------------------------------------*)
-
- PROCEDURE CurrentIRLevel ( ): IRLevel;
- (*T*)
- (* Beim 68000 wuerde auch ein 'move sr, d0' ausreichen, um an die
- aktuelle Interruptmaske zu kommen, ist aber ein 68010/20 im Rechner,
- kann der Befehl nur im Supervisormodus ausgefuehrt werden.
- *)
- BEGIN
- (*
- oldsr EQU 10*4+4 ; Offset des SR im Registerpuffer
- savptr EQU $4A2 ; Zeiger auf den Registerpuffer
- irmsk EQU $0700
-
- Supexec EQU 38
- Xbios EQU 14
- RETURN EQU 12
-
- CurrentIRLevel:
- pea getir(pc) ; Adresse der auszufuehrenden Prozedur
- move.w #Supexec, -(sp) ; Prozedur im Supervisormodus ausfuehren
- trap #Xbios ;
- bra.s ende ; fertig
-
- getir:
- movea.l savptr, a1 ; a1 -> Speicher fuer gerettete Register
- move.w oldsr(a1), d7 ; d7 := gerettetes Statusregister
- andi.w #irmsk, d7 ; d7 := IR-maske
- lsr.w #8, d7 ; als CARDINAL-Wert
- move.b d7, RETURN(a6)
- rts
-
- ende:
- *)
- INLINE( 487AH,000AH,3F3CH,0026H,4E4EH,6016H,2279H,0000H,04A2H );
- INLINE( 3E29H,002CH,0247H,0700H,0E04FH,1D47H,000CH,4E75H );
-
- END CurrentIRLevel;
-
- (*---------------------------------------------------------------------------*)
-
- PROCEDURE SetIRLevel ((* EIN/ -- *) irlevel : IRLevel );
- (*T*)
- BEGIN
- (*
- oldsr EQU 10*4+4
- savptr EQU $4A2
- expmsk EQU $0700
-
- Supexec EQU 38
- Xbios EQU 14
- irlevel EQU 12
-
- SetIRLevel:
- pea setir(pc)
- move.w #Supexec, -(sp)
- trap #Xbios
- bra.s ende
-
- setir:
- movea.l savptr, a1 ; a1 -> Speicher fuer gerettete Register
- move.w oldsr(a1), d0 ; d0 := gerettetes Statusregister
- moveq #0, d1 ; IR-Maske auf Wortlaenge
- move.b irlevel(a6), d1 ;
- lsl.w #8, d1 ; an die Position der IR-Maske im SR bringen
- andi.w #$FFFF-expmsk, d0; alte IR-Maske loeschen
- or.w d1, d0 ; und neue setzen
- move.w d0, oldsr(a1) ; neue wird bei RTE gesetzt
- rts
-
- ende:
- *)
- INLINE( 487AH,000AH,3F3CH,0026H,4E4EH,601EH,2279H,0000H,04A2H );
- INLINE( 3029H,002CH,7200H,122EH,000CH,0E149H,0240H,0F8FFH,8041H );
- INLINE( 3340H,002CH,4E75H );
-
- END SetIRLevel;
-
-
- END MACHINE.
-